//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_IDECTRLR_H__
#define __ELASTOS_IDECTRLR_H__

//
// IDEController
//
#define DRIVES_PER_CONTROLLER   2

typedef struct DriveInfo
{
    AddressingMode  preferredAddressingMode;
    bool_t          bDMASupported;
    uint16_t        u16NumberOfLogicalCylinders;
    uint16_t        u16NumberOfLogicalHeads;
    uint16_t        u16NumberOfLogicalSectorsPerTrack;
    uint32_t        u32NumberOfLBASectors;
} DriveInfo;

class IDEController : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    virtual void Dispose();

public:
    IDEController():m_nIDECommand(IDECommand_NOP),
        m_eventIsr(DzEvent(TRUE, UNSIGNALED)),m_mutexRW(DzMutex())
    {
    }

    ECode Initialize(uint_t uControllerNo);

    ECode ReadSectors(
        uint_t uDriveNo, uint32_t u32LogicalSectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToRead, uint_t *puNumberOfSectorsRead);

    ECode WriteSectors(
        uint_t uDriveNo, uint32_t u32LogicalSectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToWrite, uint_t *puNumberOfSectorsWritten);

    ECode ReadSectors(
        uint_t uDriveNo, uint16_t u16CylinderNo, uint8_t u8HeadNo,
        uint8_t u8SectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToRead, uint_t *puNumberOfSectorsRead);

    ECode WriteSectors(
        uint_t uDriveNo, uint16_t u16CylinderNo, uint8_t u8HeadNo,
        uint8_t u8SectorNo, uint8_t *pu8Buffer,
        uint_t uNumberOfSectorsToWrite, uint_t *puNumberOfSectorsWritten);

    void Isr();

private:
    ECode InitializeDevice(uint_t uDevice);

public:
    uint_t      m_uControllerNo;
    ioport_t    m_iobase;
    irq_t       m_irq;
    DriveInfo   m_driveInfos[DRIVES_PER_CONTROLLER];
    int         m_nIDECommand;
    DzEvent       m_eventIsr;
    DzMutex       m_mutexRW;
};

#endif // __ELASTOS_IDECTRLR_H__
